home *** CD-ROM | disk | FTP | other *** search
/ 3D GFX / 3D GFX.iso / pcutils / os2 / imshow / source / imshow.c < prev    next >
Encoding:
Text File  |  1995-12-31  |  80.2 KB  |  1,640 lines

  1. /******************   "IMSHOW.C" Source Code File  *************************/
  2. /*                                                                         */
  3. /* PROGRAM-NAME: IMSHOW                                                    */
  4. /* -------------                                                           */
  5. /*                                                                         */
  6. /*                                                                         */
  7. /* DEVELOPED BY:                                                           */
  8. /* -------------                                                           */
  9. /*  Martin Erzberger, 1989/93                                              */
  10. /*                                                                         */
  11. /*                                                                         */
  12. /* PURPOSE OF THE APPLICATION:                                             */
  13. /* ---------------------------                                             */
  14. /*  - Display of pictures in the formats:                                  */
  15. /*     im ("a general purpose image file format")                          */
  16. /*     bmp (OS/2 and Windows 3 Bitmaps)                                    */
  17. /*     GIF (Graphics Interchange Format)                                   */
  18. /*                                                                         */
  19. /*                                                                         */
  20. /* VERSION: 2.02, 1/93                                                     */
  21. /* --------                                                                */
  22. /*                                                                         */
  23. /*                                                                         */
  24. /* PROGRAM HISTORY:                                                        */
  25. /* ----------------                                                        */
  26. /*  - 1.00, 12/89: First edition.                                          */
  27. /*  - 1.10,  1/90: Added conversion routines,                              */
  28. /*                 Supports new im library (0.93 beta), e.g.               */
  29. /*                  - Better error management,                             */
  30. /*                  - Can read compressed pictures,                        */
  31. /*                  - More efficient storage of IMMAP pictures,            */
  32. /*                 Userinterface now in english,                           */
  33. /*                 Userinterface now SAA compliant.                        */
  34. /*  - 1.20,  7/91: 'Realize' function of OS/2 1.2 supported,               */
  35. /*                 Can use long filenames,                                 */
  36. /*                 Can now also read Windows 3 bitmaps,                    */
  37. /*                 Better error management in the conversion routines,     */
  38. /*                 BMP2IM recognizes greyscale pictures.                   */
  39. /*  - 2.00,  11/92: Version for OS/2 2.0,                                  */
  40. /*                 im library now statically linked (it isn't reentrant    */
  41. /*                  anyway),                                               */
  42. /*                 Clipboard support gone,                                 */
  43. /*                 Supports the palette manager instead of OS/2 1.2's      */
  44. /*                   "realize" function,                                   */
  45. /*                 Can now also read GIF pictures,                         */
  46. /*  - 2.01,  11/92: Some bug fixes:                                        */
  47. /*                 'ESC=Cancel' didn't work with GIF's,                    */
  48. /*                 Better work around for 100% pictures,                   */
  49. /*                 GIF loader a bit faster.                                */
  50. /*  - 2.02,   1/93: Bug fix: Now works also on TSENG video cards,          */
  51. /*                 '100% work around' isn't necessary anymore,             */
  52. /*                 Comments translated to english.                         */
  53. /*                                                                         */
  54. /*                                                                         */
  55. /*  SOURCEFILES:                                                           */
  56. /*  ------------                                                           */
  57. /*                                                                         */
  58. /*                                                                         */
  59. /*    IMSHOW.MAK     - For NMAKE utility                                   */
  60. /*    IMSHOW.DEP     - For NMAKE utility (both generated by Workframe/2)   */
  61. /*    IMSHOW.C       - Main source code                                    */
  62. /*    IMSHOW.H       - Header file                                         */
  63. /*    IMSHOW.ICO     - Icon                                                */
  64. /*    IMSHOW.RC      - Ressources (menus, strings)                         */
  65. /*    BMLIB.C        - Procedures for bitmap handling                      */
  66. /*    BMLIB.H        - Header                                              */
  67. /*    GIFLIB.C       - Procedures for GIF file handling                    */
  68. /*    GIFLIB.C       - Header                                              */
  69. /*    FILEDLG.C      - Procedures für the "File Open" dialog               */
  70. /*    IM.H           - Header for the im library                           */
  71. /*                                                                         */
  72. /*                                                                         */
  73. /*                                                                         */
  74. /*  USED LIBRARIES:                                                        */
  75. /*  ---------------                                                        */
  76. /*                                                                         */
  77. /*    IMLIB.LIB      - im library                                          */
  78. /*                                                                         */
  79. /*  USED SOFTWARE:                                                         */
  80. /*  --------------                                                         */
  81. /*                                                                         */
  82. /*    'im' Library                                                         */
  83. /*    IBM Operating System/2, Version 2.0                                  */
  84. /*    IBM C Set/2 Compiler                                                 */
  85. /*    IBM Toolkit for OS/2 2.0                                             */
  86. /*                                                                         */
  87. /*  USED LITERATURE:                                                       */
  88. /*  ----------------                                                       */
  89. /*    IBM Operating System/2 1.2 Programming Tools and Information         */
  90. /*     IBM Corporation, 1988,                                              */
  91. /*                                                                         */
  92. /*    Kerninghan, Brian W., Ritchie, Dennis M.:                            */
  93. /*     "The C Programming Language", Second Edition,                       */
  94. /*     Prentice Hall, 1988, 1978, ISBN: 0-13-110362-8                      */
  95. /*                                                                         */
  96. /*    Petzold Charles: "Programming the OS/2 Presentation Manager",        */
  97. /*     Microsoft Press, 1989, ISBN: 1-55615-170-5                          */
  98. /*                                                                         */
  99. /*    Schildt Herbert: "OS/2 Programming: An Introduction",                */
  100. /*     McGraw-Hill, 1988, ISBN: 0-07-881427-8                              */
  101. /*                                                                         */
  102. /*                                                                         */
  103. /***************************************************************************/
  104. #define INCL_WIN                       /* Window manager headerfiles       */
  105. #define INCL_GPILOGCOLORTABLE          /* To use the palette manager       */
  106. #define INCL_GPIBITMAPS                /* Header for bitmaps               */
  107. #define INCL_GPIPRIMITIVES             /* Box, Line etc.                   */
  108. #define INCL_GPICONTROL                /* For GpiResetPS                   */
  109. #define INCL_BITMAPFILEFORMAT          /* Header for bitmapfiles           */
  110. #define INCL_ERRORS                    /* Error definitions                */
  111. #define INCL_DOSSEMAPHORES             /* Header for semaphore handling    */
  112.  
  113. #include <os2.h>                       /* Main header file                 */
  114. #include <stdlib.h>
  115. #include <stdio.h>
  116. #include <string.h>                   
  117.  
  118. #include "imshow.h"                    /* General identifiers              */
  119. #include "bmlib.h"                     /* Bitmap subroutines               */
  120. #include "giflib.h"                    /* GIF subroutines                  */
  121. #include "im.h"                        /* 'im' library header              */
  122.  
  123. /*#define DEBUG_NOPALETTE*/         /* To test a no palette manager system */
  124.  
  125.  
  126. /***************************************************************************/
  127. /* Variables to control Presentation Manager.                              */
  128. /***************************************************************************/
  129.  
  130. HAB          hab;                       /* PM anchor block handler         */
  131. HMQ          hmq;                       /* Message queue handler           */
  132. HWND         hwndClient;                /* Client area window handler      */
  133. HWND         hwndFrame;                 /* Frame window handler            */
  134. HWND         hwndHscroll, hwndVscroll;  /* Scrollbar handlers              */
  135. HWND         hwndDlg;                   /* Dialogbox handler               */
  136. HPOINTER     hptrArrow;                 /* Arrow mousepointer              */
  137. HPOINTER     hptrWait;                  /* Clock mousepointer              */
  138. HDC          hdc = NULLHANDLE;          /* Screen devicecontext handler    */
  139. HDC          hdcMem = NULLHANDLE;       /* Memory devicecontext handler    */
  140. HPS          hps = NULLHANDLE;          /* Presentationspace handler       */
  141. HPS          hpsMem = NULLHANDLE;       /* Memory pres. space handler      */
  142. HBITMAP      hbm = NULLHANDLE;          /* Bitmap handler                  */
  143. PLONG        plColTable;                /* Pointer to colormap             */
  144. PBITMAPINFO2 pbmiBitmap;                /* Pointer to bitmapinfo           */
  145. HPAL         hpal = NULLHANDLE;         /* Palette handler                 */
  146. ULONG    flCreate = FCF_TITLEBAR   |    /* Window control flags            */
  147.                     FCF_SYSMENU    |
  148.                     FCF_MENU       |
  149.                     FCF_MINMAX     |
  150.                     FCF_SIZEBORDER |
  151.                     FCF_ACCELTABLE |
  152.                     FCF_ICON       |
  153.                     FCF_TASKLIST   |
  154.                     FCF_SHELLPOSITION |
  155.                     FCF_VERTSCROLL |
  156.                     FCF_HORZSCROLL;
  157. CHAR     titleBar[80] = "imShow 2.02";  /* Titlebar text                   */
  158.  
  159.  
  160. /***************************************************************************/
  161. /* Other control variables.                                                */
  162. /***************************************************************************/
  163.  
  164. BOOL   fCmdLine = FALSE;                /* Command line argument there?    */
  165. BOOL   fFill = TRUE;                    /* Background must be erased?      */
  166. BOOL   bRealizeSupported;               /* Realizing supported?            */
  167. BOOL   fRealized = FALSE;               /* Palette realized?               */
  168. HEV    semInputReady;                   /* Loading thread can start        */
  169. HEV    semPictureReady;                 /* Picture is ready to display     */
  170. HEV    semHalt;                         /* Loading should stop             */
  171. TID    tidLoad;                         /* Thread-id of the loading thread */
  172. USHORT usMenuChecked = IDM_100;         /* The checked menu                */
  173. LONG   lScaleFactor = 100;              /* Scale factor of the picture     */
  174. ULONG  ulSemHelper;                     /* Dummy, used with semaphores     */
  175.  
  176.  
  177. /***************************************************************************/
  178. /* Variables of the application                                            */
  179. /***************************************************************************/
  180.  
  181. USHORT   usType;                        /* Picture type                    */
  182. USHORT   usStorage;                     /* Storage method                  */
  183. USHORT   usSamples;                     /* Samples per pixel               */
  184. USHORT   usDepth;                       /* Bitdepth per pixel              */
  185. USHORT   usColors;                      /* Number of picture colors        */
  186. ULONG    ulBytesPerLine;                /* Bitmap bytes per line           */
  187. CHAR     szFileSource[80];              /* Picture filename                */
  188. HFILE    hImage;                        /* Handle to GIF and BMP file      */
  189. PBYTE    pbBitmapData = NULL;           /* Buffer for imagedata            */
  190. IMAGE   *imBild;                        /* Handle to IM file               */
  191. IMBYTE  *imbRowBuff = NULL;             /* Pointer to IM rowbuffer         */
  192.  
  193. ULONG  ulDisplayColors;                 /* Number of screen colors         */
  194.  
  195. ULONG  ulSizeX, ulSizeY;                /* Size of the picture             */
  196. LONG   cxClient, cyClient;              /* Size of the client area         */
  197. LONG   cxEdge, cyEdge;                  /* First visible picture dot       */
  198. LONG   cxScaled, cyScaled;              /* Size of the scaled picture      */
  199. LONG   cxCut, cyCut;                    /* Size of visible part            */
  200. BOOL   fPicReadOK = FALSE;              /* Picture was read in OK?         */
  201.  
  202.  
  203. /***************************************************************************/
  204. /* Prototypes of functions.                                                */
  205. /***************************************************************************/
  206.  
  207. INT              main (int argc, char *argv[]);
  208. MRESULT EXPENTRY WinProc (HWND, USHORT, MPARAM, MPARAM);
  209. VOID             Init (HWND);
  210. VOID             Paint (HWND);
  211. VOID             SetScrollBars (LONG);
  212. BOOL             MakePalette (PBITMAPINFO2, PLONG *);
  213. MRESULT EXPENTRY AboutDlgProc (HWND, USHORT, MPARAM, MPARAM);
  214. MRESULT EXPENTRY CancelDlgProc (HWND, USHORT, MPARAM, MPARAM);
  215. MRESULT EXPENTRY PropDlgProc (HWND, USHORT, MPARAM, MPARAM);
  216. VOID             CentreDlgBox(HWND, HWND);
  217. VOID             Help (HWND);
  218. BOOL             OpenFile (HAB, HDC, HWND, HBITMAP *);
  219. VOID             ReadFile (VOID* nichts);
  220. VOID             ShowMsg (LONG, LONG, ULONG);
  221. VOID             ImErrorMsg (int);
  222. USHORT           GetFileType (CHAR *, HFILE *, IMAGE **);
  223.  
  224. extern BOOL GetFileName (CHAR *, HWND, HWND, BOOL);
  225.  
  226.  
  227. /*************************  Start of main()  *******************************/
  228. /*                                                                         */
  229. /* main() must do three things:                                            */
  230. /*  -Initialize PM (create the window, start threads etc.).                */
  231. /*  -Dispatch the messages to the correct window.                          */
  232. /*  -Release the ressources and close the application.                     */
  233. /***************************************************************************/
  234.  
  235. INT main(int argc, char *argv[])
  236. {
  237.   QMSG qmsg;                            /* Message from message queue      */
  238.  
  239.  /*************************************************************************/
  240.  /* Initialize the application and PM:                                    */
  241.  /*************************************************************************/
  242.   if (argc == 2) {                      /* Command line argument here?     */
  243.     strcpy (szFileSource, argv[1]);     /* yup, copy it into szFileSource, */
  244.     fCmdLine = TRUE;                    /* and set flag.                   */
  245.   }
  246.  
  247.   hab = WinInitialize(0);               /* Init PM                         */
  248.  
  249.   hmq = WinCreateMsgQueue(hab, 0);      /* Create message queue            */
  250.  
  251.   WinRegisterClass(                     /* Register window class           */
  252.                    hab,                 /* Anchor block handle             */
  253.                    "IMSHOWWindow",      /* Classname                       */
  254.                    (PFNWP)WinProc,      /* Address of window procedure     */
  255.                    0,                   /* No Flags                        */
  256.                    0                    /* No window words                 */
  257.                   );
  258.  
  259.   hwndFrame = WinCreateStdWindow(       /* Create window                   */
  260.                HWND_DESKTOP,            /* Desktop is parent               */
  261.                WS_VISIBLE,              /* Window is visible               */
  262.                (PULONG)&flCreate,       /* Frame control flags             */
  263.                "IMSHOWWindow",          /* Classname                       */
  264.                "",                      /* Set title later                 */
  265.                0L,                      /* No window style                 */
  266.                0,                       /* Ressources in EXE file          */
  267.                ID_RESOURCE,             /* Resource ID                     */
  268.                (PHWND)&hwndClient       /* client window handle            */
  269.               );
  270.  
  271.   DosCreateEventSem (0, &semInputReady, 0, 0);   /* Init the semaphores    */
  272.   DosCreateEventSem (0, &semPictureReady, 0, 0);
  273.   DosCreateEventSem (0, &semHalt, 0, 1);
  274.  
  275.   /* We will need this all the time, so let's allocate it here: */
  276.   pbmiBitmap = malloc (sizeof(BITMAPINFOHEADER2) + 256*sizeof(RGB2));
  277.  
  278.   _beginthread (ReadFile, 0, 8192, 0);           /* Start 2nd thread       */
  279.  
  280.  /*************************************************************************/
  281.  /* Dispatching of messages:                                              */
  282.  /*************************************************************************/
  283.   while (WinGetMsg(hab, (PQMSG)&qmsg, (HWND)NULL, 0, 0))
  284.     WinDispatchMsg(hab, (PQMSG)&qmsg);
  285.  
  286.  /*************************************************************************/
  287.  /* Close application and release ressources:                             */
  288.  /*************************************************************************/
  289.   WinDestroyWindow(hwndFrame);          /* Kill window                     */
  290.   WinDestroyMsgQueue(hmq);              /* Kill message queue              */
  291.   WinTerminate(hab);                    /* And end...                      */
  292.   return (0);
  293. }
  294. /**************************  End of main()  ********************************/
  295.  
  296.  
  297.  
  298. /********************  Start of the window procedure  **********************/
  299. /*                                                                         */
  300. /* The window procedure processes all messages from OS/2.                  */
  301. /*                                                                         */
  302. /***************************************************************************/
  303.  
  304. MRESULT EXPENTRY WinProc (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
  305. {
  306.   ULONG        ulTemp;
  307.  
  308.   switch(msg)                      /* In msg is the message                */
  309.   {
  310.  
  311.     case WM_CREATE:                /* The window was just created          */
  312.       Init(hwnd);                  /* --> call Init()                      */
  313.       break;                       /* and break to default msg handler     */
  314.  
  315.     case WM_COMMAND:               /* One of the menus was selected        */
  316.       switch (SHORT1FROMMP(mp1))   /* Which one is in mp1                  */
  317.       {
  318.  
  319.         case IDM_OPEN:                              /* "File, open"        */
  320.           OpenFile(hab, hdcMem, hwnd, &hbm);        /* --> call function   */
  321.           break;
  322.  
  323.         case IDM_QUIT:              /* Application should end              */
  324.           WinPostMsg(hwnd, WM_CLOSE, 0L, 0L);
  325.           break;
  326.  
  327.         case IDM_ABOUT:            /* About dialog box                     */
  328.           WinDlgBox(HWND_DESKTOP,  /* Desktop is parent (used for clipping)*/
  329.                     hwnd,          /* hwnd gets the messages               */
  330.                     (PFNWP)AboutDlgProc,  /* Dialog procedure              */
  331.                     0,             /* Template is in EXE file              */
  332.                     IDD_ABOUT,     /* ID of template                       */
  333.                     NULL);         /* no more data                         */
  334.           break;
  335.  
  336.         case IDM_FIT:                            /* All of the View xxx%   */
  337.         case IDM_25:
  338.         case IDM_50:
  339.         case IDM_75:
  340.         case IDM_100:
  341.         case IDM_200:
  342.         case IDM_400:
  343.         case IDM_800:
  344.           if (SHORT1FROMMP(mp1) == usMenuChecked)  /* Same as checked?     */
  345.             break;
  346.           switch (SHORT1FROMMP(mp1)) {             /* Set scale factor     */
  347.             case IDM_FIT:
  348.               lScaleFactor = 0;
  349.               break;
  350.             case IDM_25:
  351.               lScaleFactor = 25;
  352.               break;
  353.             case IDM_50:
  354.               lScaleFactor = 50;
  355.               break;
  356.             case IDM_75:
  357.               lScaleFactor = 75;
  358.               break;
  359.             case IDM_100:
  360.               lScaleFactor = 100;
  361.               break;             
  362.             case IDM_200:
  363.               lScaleFactor = 200;
  364.               break;
  365.             case IDM_400:
  366.               lScaleFactor = 400;
  367.               break;
  368.             case IDM_800:
  369.               lScaleFactor = 800;
  370.               break;
  371.           }
  372.                                                   /* Move the check mark   */
  373.           WinCheckMenuItem (WinWindowFromID(hwndFrame, FID_MENU),
  374.                             SHORT1FROMMP(mp1), TRUE);
  375.  
  376.           WinCheckMenuItem (WinWindowFromID(hwndFrame, FID_MENU),
  377.                             usMenuChecked, FALSE);
  378.  
  379.           usMenuChecked = SHORT1FROMMP(mp1);      /* Set for next time     */
  380.  
  381.           SetScrollBars (lScaleFactor);           /* Init. scrollbars      */
  382.  
  383.           fFill = TRUE;                           /* Erase background      */
  384.           WinInvalidateRect( hwnd, NULL, FALSE);  /* force redraw          */
  385.  
  386.           break;
  387.  
  388.         case IDM_PROP:             /* "Properties" dialog                  */
  389.           WinDlgBox(HWND_DESKTOP,  /* Desktop is parent (user for clipping)*/
  390.                     hwnd,          /* hwnd gets messages                   */
  391.                     (PFNWP)PropDlgProc,   /* Dialog procedure              */
  392.                     0,             /* Template is in EXE file              */
  393.                     IDD_PROP,      /* ID of template                       */
  394.                     NULL);         /* No more data                         */
  395.           break;
  396.  
  397.         case IDM_HELPHELP:         /* "Help, Help for Help"                */
  398.           Help(hwnd);              /* call Help()                          */
  399.           break;
  400.  
  401.         default:                   /* Default: break out to default        */
  402.           break;                   /* message processing                   */
  403.  
  404.       } /* End of "menu" switch */
  405.       break;
  406.  
  407.  
  408.     case WM_ERASEBACKGROUND:       /* Background has to be erased          */
  409.       fFill = TRUE;                /* Set appropriate flag                 */
  410.       return (MRESULT)(FALSE);     /* --> imShow will take care of it      */
  411.  
  412.     case WM_PAINT:                 /* A repaint is necessary               */
  413.       Paint(hwnd);                 /*  --> call Paint()                    */
  414.       break;
  415.  
  416.     case WM_SIZE:                  /* The window was resized               */
  417.       cxClient = SHORT1FROMMP(mp2);
  418.       cyClient = SHORT2FROMMP(mp2); /* Get new size                        */
  419.                                                   /* Is a picture ready?   */
  420.       if (DosWaitEventSem (semPictureReady, 0) != ERROR_TIMEOUT) {
  421.         SetScrollBars (lScaleFactor);             /* Yes, set scrollbars,  */
  422.         fFill = TRUE;                             /* erase background,     */
  423.         WinInvalidateRect( hwnd, NULL, FALSE);    /* and force redraw      */
  424.       }
  425.       break;
  426.  
  427.     case WM_REALIZEPALETTE:        /* The palette has to be re-realized    */
  428.       if (!fRealized)              /* If we don't have one currently:      */
  429.         break;                     /* --> break to default                 */
  430.       else
  431.         if (WinRealizePalette (hwndClient, hps, &ulTemp)) /* Realize it    */
  432.           WinInvalidateRect (hwnd, NULL, FALSE); /* and if necessary redraw*/
  433.       return(0);
  434.  
  435.     case WM_VSCROLL:                /* Message from vertical scrollbar     */
  436.       switch (SHORT2FROMMP (mp2)) { /* Message is in mp2                   */
  437.  
  438.         case SB_LINEUP:             /* Top arrow was clicked               */
  439.           cyEdge--;                 /* Scroll one pixel                    */
  440.           break;
  441.  
  442.         case SB_PAGEUP:             /* Click above slider                  */
  443.           cyEdge -= cyCut;          /* Scroll one screen full              */
  444.           break;
  445.  
  446.         case SB_PAGEDOWN:           /* Click below slider                  */
  447.           cyEdge += cyCut;          /* Scroll one screen full              */
  448.           break;
  449.  
  450.         case SB_LINEDOWN:           /* Bottom arrow was clicked            */
  451.           cyEdge++;                 /* Scroll one pixel                    */
  452.           break;
  453.  
  454.         case SB_SLIDERPOSITION:     /* Slider was dragged to the position  */
  455.           cyEdge = SHORT1FROMMP (mp2);   /* given im mp2                   */
  456.           break;                   
  457.  
  458.         default: return 0;          /* default: leave window procedure     */
  459.  
  460.       } /* End of vertical scrollbat switch                                */
  461.         /* The following part is reached by all case's above (except the   */
  462.         /* "default" part.                                                 */
  463.  
  464.       cyEdge = max (0, cyEdge);               /* Reset position to a valid */
  465.       cyEdge = min ((LONG)ulSizeY-cyCut, cyEdge); /* one                   */
  466.  
  467.             /* Set the slider to the new position: */
  468.         WinSendMsg (hwndVscroll, SBM_SETPOS, MPFROMSHORT (cyEdge), NULL);
  469.             /* And force a redraw: */
  470.         WinInvalidateRect (hwnd, NULL, FALSE);
  471.  
  472.       break; /* Get out of WM_VSCROLL */
  473.  
  474.     case WM_HSCROLL:                  /* Message from horizontal scrollbar */
  475.       switch (SHORT2FROMMP (mp2)) {   /* The above comments apply also here*/
  476.  
  477.         case SB_LINELEFT:              /* Left arrow                       */
  478.           cxEdge--;
  479.           break;
  480.  
  481.         case SB_PAGELEFT:              /* Left from slider                 */
  482.           cxEdge -= cxCut;
  483.           break;
  484.  
  485.         case SB_PAGERIGHT:             /* Right from slider                */
  486.           cxEdge += cxCut;
  487.           break;
  488.  
  489.         case SB_LINERIGHT:             /* Right arrow                      */
  490.           cxEdge++;
  491.           break;
  492.  
  493.         case SB_SLIDERPOSITION:        /* New position                     */
  494.           cxEdge = SHORT1FROMMP (mp2);  
  495.           break;
  496.  
  497.         default: return 0;             /* Leave window procedure           */
  498.  
  499.       } /* End of horizontal scrollbar switch */
  500.  
  501.       /* Again the common scrollbar part:                                  */
  502.  
  503.       cxEdge = max (0, cxEdge);             
  504.       cxEdge = min ((LONG)ulSizeX-cxCut, cxEdge);
  505.  
  506.         WinSendMsg (hwndHscroll, SBM_SETPOS, MPFROMSHORT (cxEdge), NULL);
  507.  
  508.         WinInvalidateRect (hwnd, NULL, FALSE);
  509.  
  510.       break; /* Leave VM_HSCROLL */
  511.  
  512.     default:      /* Default: Break to default window procedure            */
  513.       break;
  514.  
  515.   } /* End of window procedure switch */
  516.  
  517.   /* Most of the messages are now also passed to the default window        */
  518.   /* procedure. Of course, also all the not-processed messages get passed  */
  519.   /* (by the default: break statement above).                              */
  520.  
  521.   return WinDefWindowProc( hwnd, msg, mp1, mp2 );
  522. }
  523. /**********************  End of the window procedure  **********************/
  524.  
  525.  
  526.  
  527. /**************************  Start of Init()  ******************************/
  528. /*                                                                         */
  529. /*  Initializations of the window.                                         */
  530. /*                                                                         */
  531. /*  The initializations for the window must be done here, since only at    */
  532. /*  this place the window is already created, and one can ask e.g. the     */
  533. /*  size of it.                                                            */
  534. /*                                                                         */
  535. /***************************************************************************/
  536.  
  537. VOID Init(HWND hwnd)    /* We only need hwnd from the WM_CREATE message.   */
  538. {
  539.   SIZEL sizlTemp;
  540.   LONG  plTempArray[1];
  541.  
  542.   DosResetEventSem (semPictureReady, &ulSemHelper); /* Picture not ready   */
  543.  
  544.   /* We will need the scroll bars a lot, so we will get their ID's at this */
  545.   /* place and put them in a global variable. Because hwndFrame isn't      */
  546.   /* known yet, the somewhat complicated methot with QW_PARENT is used.    */
  547.   hwndHscroll = WinWindowFromID
  548.                  (WinQueryWindow (hwnd, QW_PARENT), FID_HORZSCROLL);
  549.   hwndVscroll = WinWindowFromID
  550.                  (WinQueryWindow (hwnd, QW_PARENT), FID_VERTSCROLL);
  551.  
  552.   /* We will also need the arrow and the clock pointer, so                 */
  553.   /* we get their ID's also                                                */
  554.   hptrArrow = WinQuerySysPointer (HWND_DESKTOP, SPTR_ARROW, FALSE);
  555.   hptrWait  = WinQuerySysPointer (HWND_DESKTOP, SPTR_WAIT, FALSE);
  556.  
  557.   /* Now we set the titlebar text:                                         */
  558.   WinSetWindowText (WinQueryWindow (hwnd, QW_PARENT), titleBar);
  559.  
  560.   /* The following gets the size of a maximized window:                    */
  561.   sizlTemp.cx = (LONG)((WinQuerySysValue (HWND_DESKTOP, SV_CXFULLSCREEN)-
  562.                         WinQuerySysValue (HWND_DESKTOP, SV_CXVSCROLL) + 1));
  563.   sizlTemp.cy = (LONG)((WinQuerySysValue (HWND_DESKTOP, SV_CYFULLSCREEN)-
  564.                         WinQuerySysValue (HWND_DESKTOP, SV_CYMENU)-
  565.                         WinQuerySysValue (HWND_DESKTOP, SV_CYHSCROLL) + 1));
  566.  
  567.   /* Now we open a window device context to get some device capabilities: */
  568.   hdc = WinOpenWindowDC (hwnd);  
  569.     if (hdc == (HDC)NULL) exit(1);  /* Again, not very nice...            */
  570.  
  571.   DevQueryCaps (hdc, CAPS_COLORS, 1L, plTempArray);
  572.   ulDisplayColors = (ULONG)plTempArray[0]; /* Number of display colors    */
  573.  
  574.   /* Is the palette manager supported?                                    */
  575.   DevQueryCaps (hdc, CAPS_ADDITIONAL_GRAPHICS, 1L, plTempArray);
  576.   bRealizeSupported = (BOOL)((plTempArray[0] & CAPS_PALETTE_MANAGER));
  577.  
  578. #ifdef DEBUG_NOPALETTE
  579.   bRealizeSupported = FALSE;
  580. #endif
  581.  
  582.   /* Now we create a presentation space (we will keep this one until      */
  583.   /* the application ends).                                               */
  584.   hps = GpiCreatePS (hab, hdc, &sizlTemp,
  585.                      GPIA_ASSOC | PU_PELS | GPIF_DEFAULT);
  586.   if (hps == (HPS)NULL) exit(1);
  587.  
  588.   /* Is there a file with the name specified on the command line?          */
  589.   if (fCmdLine) {                         /* Was there an argument?        */
  590.     if (fopen (szFileSource, "rb") == NULL) /* Try to open the file        */
  591.       fCmdLine = FALSE;                   /* Nope, --> clear flag          */
  592.     else {
  593.       _fcloseall();                       /* Yes: Close file again         */
  594.                                           /* and simulate a menu choice:   */
  595.       WinPostMsg (hwndFrame, WM_COMMAND, MPFROMSHORT(IDM_OPEN), NULL);
  596.     } /* End if (fopen...) */
  597.   } /* End if (FCmdLine) */
  598. } /* End Init() */
  599.  
  600. /***************************  End of Init()  *******************************/
  601.  
  602.  
  603.  
  604. /**************************  Start of Paint()  *****************************/
  605. /*                                                                         */
  606. /*  Paint() processes the WM_PAINT messages of OS/2 PM.                    */
  607. /*                                                                         */
  608. /*  We always get a WM_PAINT message if parts of the client area become    */
  609. /*  invalid, e.g. by hiding and unhiding it by another window.             */
  610. /*                                                                         */
  611. /*  One can force a WM_PAINT message by declaring the window as invalid    */
  612. /*  with the WinInvalidateRect call.                                       */
  613. /*                                                                         */
  614. /***************************************************************************/
  615.  
  616. VOID       Paint(HWND hwnd)  /* We only need the window handler            */
  617.                              /* mp1 and mp2 are NULL anyway...             */
  618. {
  619.   RECTL rc;                  /* Update region.                             */
  620.   RECTL rcSource, rcDest;    /* Source and target rectangles for bitmap    */
  621.  
  622.  
  623.   WinQueryUpdateRect (hwnd, &rc); /* Get the update region                 */
  624.  
  625.  
  626. /***************************************************************************/
  627. /* We don't need the semaphore below for synchronisation, we just want     */
  628. /* to know if there is a picture ready to display. We get this information */
  629. /* by setting a timeout of 0, and then asking wether there was a timeout   */
  630. /* or not.                                                                 */
  631. /* If the semaphore was busy, then there is no picture ready yet, and we   */
  632. /* simply draw the whole client area black.                                */
  633. /***************************************************************************/
  634.   if (DosWaitEventSem (semPictureReady, 0L) == ERROR_TIMEOUT)
  635.     WinFillRect (hps, &rc, CLR_BLACK);
  636.  
  637.   else {                                /* Ok, there is a picture          */
  638.     if (fFill)                          /* Do we have to reset the back-   */
  639.                                         /* ground first?                   */
  640.       WinFillRect (hps, &rc, CLR_BLACK);/* Yes: Fill it black              */
  641.  
  642.     fFill = FALSE;                     /* Reset flag                       */
  643.  
  644.     /* Next, we have to state which part of the bitmap we want to copy     */
  645.     /* in what rectangle:                                                  */
  646.     rcDest.xLeft = 0;                  /* Dest., bottom left               */
  647.     rcDest.yBottom = 0;                /*                                  */
  648.  
  649.     if (cxCut > (LONG)ulSizeX) {       /* Picture is slimmer than window:  */
  650.       rcDest.xRight = cxScaled;        /* Destination, right               */
  651.       rcSource.xLeft = 0;              /* Source, left                     */
  652.       rcSource.xRight = (LONG)ulSizeX; /* Source, right                    */
  653.     } else {                           /* Picture is broader than window:  */
  654.     rcDest.xRight = cxClient;          /* Destination, right:              */
  655.     rcSource.xLeft = cxEdge;           /* Source, left                     */
  656.     rcSource.xRight = cxCut + cxEdge;  /* Source, right                    */
  657.     }
  658.  
  659.     if (cyCut > (LONG)ulSizeY) {       /* Picture is less high than window */
  660.       rcDest.yTop = cyScaled;          /* Destination, top                 */
  661.       rcSource.yBottom = 0;            /* Source, bottom                   */
  662.       rcSource.yTop = (LONG)ulSizeY;   /* Source, top                      */
  663.     } else {                           /* Picture is higher than window:   */
  664.     rcDest.yTop = cyClient;            /* Destination, top                 */
  665.     rcSource.yBottom = cyEdge;         /* Source, bottom                   */
  666.     rcSource.yTop = cyCut + cyEdge;    /* Source, top                      */
  667.     }
  668.  
  669.   /* The copy can take a while, so let's set the clock pointer:            */
  670.   WinSetPointer (HWND_DESKTOP, hptrWait);
  671.  
  672.   WinDrawBitmap(hps,                      /* Draw the bitmap...            */
  673.                 hbm,                      /* From hbm to hps               */
  674.                 &rcSource,
  675.                 (PPOINTL)&rcDest,
  676.                 0,
  677.                 1,
  678.                 DBM_NORMAL | DBM_STRETCH  /* Stretch the bitmap            */
  679.                );
  680.  
  681.   WinSetPointer (HWND_DESKTOP, hptrArrow); /* Reset the pointer again..    */
  682.  
  683.   }  /* End if */
  684.  
  685.   WinValidateRect (hwnd, &rc, FALSE); /* Window is now valid again.        */
  686. }
  687. /***************************  End of Paint()  ******************************/
  688.  
  689.  
  690.  
  691. /***********************  Start of SetScrollBars()  ************************/
  692. /*                                                                         */
  693. /* SetScrollBars() initializes the scrollbars after a new file was loaded, */
  694. /* after a WM_SIZE message or when the scale rate was changed.             */
  695. /*                                                                         */
  696. /***************************************************************************/
  697.  
  698. VOID SetScrollBars(LONG lScaleFactor)
  699. {
  700.   cxEdge = 0;       /* Reset the bottom left corner of the visible         */
  701.   cyEdge = 0;       /* bitmap                                              */
  702.  
  703.  
  704.   if (ulSizeX == 0 || ulSizeY == 0) {           /* Wrong picture??         */
  705.      cxScaled = 0;
  706.      cyScaled = 0;
  707.      cxCut = 0;
  708.      cyCut = 0;
  709.      ulSizeX = 0;
  710.      ulSizeY = 0;
  711.   } else {                                     /* Picture ok               */
  712.     if (lScaleFactor == 0) {                   /* i.e. "fit in window"     */
  713.       cyScaled = (LONG)ulSizeY * cxClient / (LONG)ulSizeX; /* Try to fit y */
  714.       if (cyScaled > cyClient) {               /* Too big?                 */
  715.         cyScaled = cyClient;                   /* let y be,                */
  716.         cxScaled = (LONG)ulSizeX * cyClient / (LONG)ulSizeY; /* and fit x  */
  717.       } else                                   /* fit y,                   */
  718.         cxScaled = cxClient;                   /* and let x be             */
  719.     } else {                                   /* other scale factor       */
  720.       cxScaled = (lScaleFactor * (LONG)ulSizeX) / 100; /* scale x,         */
  721.       cyScaled = (lScaleFactor * (LONG)ulSizeY) / 100; /* and y            */
  722.     } /* End if lScaleFactor == 0 */
  723.  
  724.     /* Now we have to calculate the amount of pixels that can be seen at   */
  725.     /* once. So if e.g. cxCut results to 30, 30 pixels of the source       */
  726.     /* bitmap data will fit in the x direction. One could also say, cxCut  */
  727.     /* is one "page" of the bitmap. If the window is 120 pixels            */
  728.     /* wide, the image is 240 pixels wide, and the scale factor is 200%,   */
  729.     /* then 30 pixels will fit. Easy, isn't it?                            */
  730.     if (lScaleFactor == 0) { /* Again: option "fit in window"              */
  731.       cxCut = (LONG)ulSizeX * cxClient / cxScaled; 
  732.       cyCut = (LONG)ulSizeY * cyClient / cyScaled;
  733.     } else {                                     /* Other scale factor:    */
  734.       cxCut = (100 * cxClient) / lScaleFactor;   /* Obvious                */
  735.       cyCut = (100 * cyClient) / lScaleFactor;
  736.     } /* End if lScaleFactor == 0 */
  737.   } /* End if Picture ok? */
  738.  
  739.  
  740.   if (cxClient >= cxScaled)                  /* Window bigger than picture */
  741.     WinEnableWindow (hwndHscroll, FALSE);    /* -> Switch off scrollbar    */
  742.   else {                                     /* Picture bigger than window */
  743.     WinEnableWindow (hwndHscroll, TRUE);     /* -> Switch on scrollbar     */
  744.  
  745.   /* Now we set the endpoints of the scrollbar. The value range goes from  */
  746.   /* 0 to ulSizeX - cxCut. Why this? With 0, one can see the first cxCut   */
  747.   /* pixels, and with ulSizeX-cxCut, one can see the last cxCut pixels...  */
  748.   /* To go higher wouldn't make sense, one would have to put a blank bar   */
  749.   /* to the left of the picture.                                           */
  750.     WinSendMsg (hwndHscroll, SBM_SETSCROLLBAR, /* Set endpoints of scroll- */
  751.                 MPFROM2SHORT (0, 0),           /* bar and put slider on    */
  752.                 MPFROM2SHORT (0, (LONG)ulSizeX - cxCut));  /* position 0   */
  753.   /* Then we set the slider size: It is set by giving the two values       */
  754.   /* "visible part" and "total part", which is cxCut and ulSizeX here.     */
  755.     WinSendMsg (hwndHscroll, SBM_SETTHUMBSIZE, /* Set the size of the      */
  756.                 MPFROM2SHORT (cxCut, ulSizeX), /* slider                   */
  757.                 MPFROM2SHORT (0,0));
  758.   } /* End if window bigger as picture */
  759.  
  760.   if (cyClient >= cyScaled)                  /* Same stuff for the         */
  761.     WinEnableWindow (hwndVscroll, FALSE);    /* vertical scrollbar         */
  762.   else {
  763.     WinEnableWindow (hwndVscroll, TRUE);
  764.     WinSendMsg (hwndVscroll, SBM_SETSCROLLBAR,
  765.                 MPFROM2SHORT (0, 0),
  766.                 MPFROM2SHORT (0, (LONG)ulSizeY - cyCut));
  767.     WinSendMsg (hwndVscroll, SBM_SETTHUMBSIZE,
  768.                 MPFROM2SHORT (cyCut, ulSizeY),
  769.                 MPFROM2SHORT (0,0));
  770.   }
  771. }
  772.  
  773. /*************************  End of SetScrollBars()  ************************/
  774.  
  775.  
  776.  
  777. /************************  Start of MakePalette()  *************************/
  778. /*                                                                         */
  779. /* MakePalette creates the palette.                                        */
  780. /*                                                                         */
  781. /***************************************************************************/
  782.  
  783. BOOL MakePalette (PBITMAPINFO2 pbmi, PLONG *plTable)
  784. {
  785.   ULONG i, ulTemp;
  786.  
  787.   switch (pbmi->cBitCount) {     /* Get the size of the table              */
  788.  
  789.     case 8:                      /* 8 bits, --> 256 color entries          */
  790.       *plTable = malloc (256 * sizeof (LONG));
  791.       break;
  792.  
  793.     case 4:                      /* 4 bits, --> 16 color entries           */
  794.       *plTable = malloc (16 * sizeof (LONG));
  795.       break;
  796.  
  797.     default:                     /* other value shouldn't appear...        */
  798.       return FALSE;
  799.   } /* Ende switch */
  800.  
  801.   if (*plTable == NULL)
  802.     exit(1);
  803.  
  804.   for (i=0; i<usColors; i++) {   /* Fill the table with the colors         */
  805.     (*plTable)[i] = (pbmi->argbColor[i].bRed   * 65536L +
  806.                      pbmi->argbColor[i].bGreen *   256L +
  807.                      pbmi->argbColor[i].bBlue);
  808.   }
  809.   hpal = GpiCreatePalette (hab, 0, LCOLF_CONSECRGB, /* Create palette      */
  810.                            (LONG)usColors, (PULONG)*plTable);
  811.   free (plTable);
  812.   GpiSelectPalette (hps, hpal);                 /* Select palette into hps */
  813.   WinRealizePalette (hwndClient, hps, &ulTemp); /* and realize it          */
  814.   fRealized = TRUE;                             /* set flag                */
  815.   return TRUE;
  816. }
  817. /**************************  End of MakePalette()  *************************/
  818.  
  819.  
  820.  
  821. /****************  Start of the About Box window procedure  ****************/
  822. /*                                                                         */
  823. /* Handles the messages to the "About" box.                                */
  824. /*                                                                         */
  825. /***************************************************************************/
  826.  
  827. MRESULT EXPENTRY AboutDlgProc(HWND hwndDlg, USHORT msg,
  828.                               MPARAM mp1, MPARAM mp2)
  829. {
  830.   switch(msg)
  831.   {
  832.     case WM_INITDLG:         /* On init, the box will be centered.         */
  833.       CentreDlgBox (hwndDlg, hwndClient);
  834.       break;
  835.  
  836.     default: break;
  837.   }
  838.   return WinDefDlgProc(hwndDlg, msg, mp1, mp2);
  839. }
  840. /*****************  End of the About Box window procedure  *****************/
  841.  
  842.  
  843.  
  844. /***************  Start of the Cancel Box window procedure  ****************/
  845. /*                                                                         */
  846. /* Processes the messages to the "Cancel" box.                             */
  847. /*                                                                         */
  848. /* This dialog box appears while loading a picture, and gives the option   */
  849. /* to cancel the loading procedure.                                        */
  850. /*                                                                         */
  851. /***************************************************************************/
  852.  
  853. MRESULT EXPENTRY CancelDlgProc(HWND hwndDlg, USHORT msg,
  854.                                MPARAM mp1, MPARAM mp2)
  855. {
  856.   switch(msg) {
  857.  
  858.   case WM_INITDLG:
  859.     /* Set " % loaded" to 0:                                               */
  860.     WinSetDlgItemShort (hwndDlg, IDD_PERCENT, 0, FALSE);
  861.     CentreDlgBox (hwndDlg, hwndClient);  /* And center the dialog box      */
  862.     break;
  863.  
  864.   case WM_COMMAND:
  865.     switch(COMMANDMSG(&msg)->cmd) {
  866.     case DID_CANCEL:          /* User wants to cancel the loading process  */
  867.       DosResetEventSem (semHalt, &ulSemHelper); /* --> inform the thread   */
  868.       return 0;
  869.     }
  870.     break;
  871.  
  872.   case WM_PROGRESS:
  873.     /* The percent field must be updated                                   */
  874.     WinSetDlgItemShort (hwndDlg, IDD_PERCENT, SHORT1FROMMP(mp1), FALSE);
  875.     break;
  876.  
  877.   case WM_FINISHED:             /* The loading thread is finished          */
  878.     WinDismissDlg(hwndDlg, TRUE); /* --> End the dialog                    */
  879.     return 0;
  880.   }
  881.   return WinDefDlgProc(hwndDlg, msg, mp1, mp2);
  882. }
  883. /****************  End of the Cancel Box window procedure  *****************/
  884.  
  885.  
  886.  
  887. /****************  Start of the Param Box window procedure  ****************/
  888. /*                                                                         */
  889. /* Processes the messages to the "Param" dialog box.                       */
  890. /*                                                                         */
  891. /* The "Param" box displays the file properties.                           */
  892. /*                                                                         */
  893. /***************************************************************************/
  894.  
  895. MRESULT EXPENTRY PropDlgProc(HWND hwndDlg, USHORT msg,
  896.                              MPARAM mp1, MPARAM mp2)
  897.  
  898. {
  899.   switch(msg) {
  900.   case WM_INITDLG:
  901.     CentreDlgBox (hwndDlg, hwndClient); /* Centre box on init              */
  902.  
  903.     switch (usStorage) {  /* Set storage type                              */
  904.     case IMRAW:
  905.       WinSetDlgItemText (hwndDlg, IDD_STORAGE, "IMRAW");
  906.       break;
  907.  
  908.     case IMRLE:
  909.       WinSetDlgItemText (hwndDlg, IDD_STORAGE, "IMRLE");
  910.       break;
  911.  
  912.     case IMLZW:
  913.       WinSetDlgItemText (hwndDlg, IDD_STORAGE, "IMLZW");
  914.       break;
  915.  
  916.     default:
  917.       WinSetDlgItemText (hwndDlg, IDD_STORAGE, "?");
  918.     }
  919.  
  920.     switch (usType) {                   /* Set file type                   */
  921.     case OS2_101:
  922.       WinSetDlgItemText (hwndDlg, IDD_TYPE, "OS/2, 1.1");
  923.       WinSetDlgItemText (hwndDlg, IDD_STORAGE, "RAW");
  924.       break;
  925.  
  926.     case WIN_3:
  927.       WinSetDlgItemText (hwndDlg, IDD_TYPE, "WIN 3");
  928.       WinSetDlgItemText (hwndDlg, IDD_STORAGE, "RAW");
  929.       break;
  930.  
  931.     case GIF:
  932.       WinSetDlgItemText (hwndDlg, IDD_TYPE, "GIF");
  933.       WinSetDlgItemText (hwndDlg, IDD_STORAGE, "GIF");
  934.       break;
  935.  
  936.     case OS2_200:
  937.       WinSetDlgItemText (hwndDlg, IDD_TYPE, "OS/2, 2.0");
  938.  
  939.       switch (usStorage) {
  940.       case BCA_UNCOMP:
  941.         WinSetDlgItemText (hwndDlg, IDD_STORAGE, "RAW");
  942.         break;
  943.  
  944.       case BCA_HUFFMAN1D:
  945.         WinSetDlgItemText (hwndDlg, IDD_STORAGE, "HUFFM");
  946.         break;
  947.  
  948.       case BCA_RLE4:
  949.         WinSetDlgItemText (hwndDlg, IDD_STORAGE, "RLE4");
  950.         break;
  951.  
  952.       case BCA_RLE8:
  953.         WinSetDlgItemText (hwndDlg, IDD_STORAGE, "RLE8");
  954.         break;
  955.  
  956.       case BCA_RLE24:
  957.         WinSetDlgItemText (hwndDlg, IDD_STORAGE, "RLE24");
  958.         break;
  959.  
  960.       default:
  961.         WinSetDlgItemText (hwndDlg, IDD_STORAGE, "?");
  962.       } /* endswitch */
  963.       break;
  964.  
  965.     case IMGRY:
  966.       WinSetDlgItemText (hwndDlg, IDD_TYPE, "IMGRY");
  967.       break;
  968.  
  969.     case IMRGB:
  970.       WinSetDlgItemText (hwndDlg, IDD_TYPE, "IMRGB");
  971.       break;
  972.  
  973.     case IMMAP:
  974.       WinSetDlgItemText (hwndDlg, IDD_TYPE, "IMMAP");
  975.       break;
  976.  
  977.     case IMFLT:
  978.       WinSetDlgItemText (hwndDlg, IDD_TYPE, "IMFLT");
  979.       break;
  980.  
  981.     default:
  982.       WinSetDlgItemText (hwndDlg, IDD_TYPE, "?");
  983.     }
  984.  
  985.  
  986.  
  987.   WinSetDlgItemShort (hwndDlg, IDD_SIZEX,   (USHORT)ulSizeX, FALSE);
  988.   WinSetDlgItemShort (hwndDlg, IDD_SIZEY,   (USHORT)ulSizeY, FALSE);
  989.   WinSetDlgItemShort (hwndDlg, IDD_SAMPLES, usSamples,       FALSE);
  990.   WinSetDlgItemShort (hwndDlg, IDD_DEPTH,   usDepth,         FALSE);
  991.   WinSetDlgItemShort (hwndDlg, IDD_COLORS,  usColors,        FALSE);
  992.  
  993.   break;
  994.  
  995.   default: break;
  996.  
  997.   }
  998.   return WinDefDlgProc(hwndDlg, msg, mp1, mp2);
  999. }
  1000. /*****************  End of the Param Box window procedure  *****************/
  1001.  
  1002.  
  1003.  
  1004.  
  1005. /***********************  Start of CentreDlgBox()  *************************/
  1006. /*                                                                         */
  1007. /*  CentreDlgBox places the given dialog box in the center of the          */
  1008. /*  stated window.                                                         */
  1009. /*                                                                         */
  1010. /***************************************************************************/
  1011.  
  1012. VOID CentreDlgBox(HWND hwndDlg, HWND hwndParent)
  1013. {
  1014.   LONG  ix, iy;                     /* New position of the dialog box      */
  1015.   LONG  iwidth, idepth;             /* Size of the display                 */
  1016.   SWP   swp;                        /* Window informations                 */
  1017.   RECTL rect;                       /* Size of the window                  */
  1018.  
  1019.   /*************************************************************************/
  1020.   /* Get size of display                                                   */
  1021.   /*************************************************************************/
  1022.   iwidth = (SHORT)WinQuerySysValue (HWND_DESKTOP, SV_CXSCREEN );
  1023.   idepth = (SHORT)WinQuerySysValue (HWND_DESKTOP, SV_CYSCREEN );
  1024.  
  1025.   /*************************************************************************/
  1026.   /* Get size of window and norm it to screen                              */
  1027.   /*************************************************************************/
  1028.   WinQueryWindowRect (hwndParent, &rect);
  1029.   WinMapWindowPoints (hwndParent, HWND_DESKTOP, (PPOINTL)&rect, 2);
  1030.  
  1031.   /*************************************************************************/
  1032.   /* Get window informations of the dialog box                             */
  1033.   /*************************************************************************/
  1034.   WinQueryWindowPos (hwndDlg, (PSWP)&swp);
  1035.  
  1036.   /*************************************************************************/
  1037.   /* Calculate new position                                                */
  1038.   /*************************************************************************/
  1039.   ix = ((rect.xRight - rect.xLeft   - swp.cx) / 2) + rect.xLeft;
  1040.   iy = ((rect.yTop   - rect.yBottom - swp.cy) / 2) + rect.yBottom;
  1041.  
  1042.   /*************************************************************************/
  1043.   /* Make shure, that the box is totally visible                           */
  1044.   /*************************************************************************/
  1045.   ix = max (ix, 0);
  1046.   ix = min (ix, (iwidth - swp.cx));
  1047.  
  1048.   iy = max (iy, 0);
  1049.   iy = min (iy, (idepth - swp.cy));
  1050.  
  1051.   /*************************************************************************/
  1052.   /* Set the new position                                                  */
  1053.   /*************************************************************************/
  1054.   WinSetWindowPos( hwndDlg, HWND_TOP, ix, iy, 0, 0, SWP_MOVE );
  1055. }
  1056. /************************  End of CentreDlgBox()  **************************/
  1057.  
  1058.  
  1059.  
  1060. /***************************  Start of  Help()  ****************************/
  1061. /*                                                                         */
  1062. /*  There is no online help in this application (well, there's no offline  */
  1063. /*  help either...).                                                       */
  1064. /*  This function call merely gives this information.                      */
  1065. /*                                                                         */
  1066. /***************************************************************************/
  1067. VOID Help(HWND hwnd)
  1068. {
  1069.   char title[20];
  1070.   char help[200];
  1071.  
  1072.   WinLoadString(hab,             /* Get title of help box                  */
  1073.                 0,
  1074.                 IDS_HELPTITLE,
  1075.                 20,
  1076.                 title
  1077.                );
  1078.   WinLoadString(hab,             /* Get content string of help box         */
  1079.                 0,
  1080.                 IDS_HELP,
  1081.                 200,
  1082.                 help
  1083.                );
  1084.   WinMessageBox(HWND_DESKTOP,    /* Display help box                       */
  1085.                 hwnd,
  1086.                 help,
  1087.                 title,
  1088.                 0,
  1089.                 MB_OK | MB_NOICON
  1090.                );
  1091.   /* Don't know how to remove the WC_SAVEBITS option, so the whole         */
  1092.   /* window has to be invalidated (see also imShow.rc)                     */
  1093.   WinInvalidateRect( hwnd, NULL, FALSE);       
  1094. }
  1095. /****************************  End of Help()  ******************************/
  1096.  
  1097.  
  1098.  
  1099. /**************************  Begin of OpenFile()  **************************/
  1100. /*                                                                         */
  1101. /* OpenFile() will be called when the user selects "File, open" or when    */
  1102. /* there was a valid command line argument.                                */
  1103. /*                                                                         */
  1104. /***************************************************************************/
  1105.  
  1106. BOOL OpenFile(HAB hab, HDC hdcMem, HWND hwnd, HBITMAP *hbm)
  1107. {
  1108.   ULONG       ulTemp;
  1109.   ULONG       ulIndex;
  1110.   LONG        lReturn;
  1111.   IMBYTE      *pimMap;
  1112.   SIZEL       size;                /* Size of presentation space           */
  1113.  
  1114.  
  1115.   if (fCmdLine) fCmdLine = FALSE;  /* Was there an argument on startup?    */
  1116.                                    /* No: show file dialogbox:             */
  1117.   else if (!GetFileName (szFileSource, HWND_DESKTOP, hwnd, TRUE))
  1118.          return 0;
  1119.  
  1120.   fFill = TRUE;                    /* Window has to be cleared afterwards  */
  1121.  
  1122.   usType = GetFileType (szFileSource, &hImage, &imBild); /* Get type       */
  1123.  
  1124.   /* The not used fields of pbmiBitmap MUST be 0, or OS/2 will choke       */
  1125.   memset (pbmiBitmap, 0, sizeof (BITMAPINFOHEADER2)+256*sizeof(RGB2));
  1126.  
  1127.   switch (usType) {
  1128.   case BITMAP:                     /* File is a bitmap                     */
  1129.     bmrhdr (hImage, pbmiBitmap);              /* Read in the header        */
  1130.   
  1131.     ulSizeX = pbmiBitmap->cx;      /* Copy some parameters into globals    */
  1132.     ulSizeY = pbmiBitmap->cy;
  1133.   
  1134.      /* Now distinguish the type even further:                             */
  1135.     if (pbmiBitmap->cbFix == 12)   /* Must be an OS/2 1.1 bitmap           */
  1136.       usType  = OS2_101;
  1137.     else if ((pbmiBitmap->cbFix < 41) &&  /* A Win 3 header is smaller     */
  1138.                                  /* and doesn't support compressed bitmaps */
  1139.              (pbmiBitmap->ulCompression == BCA_UNCOMP))
  1140.       usType = WIN_3;
  1141.     else usType = OS2_200;
  1142.     /* We stuff all bitmaps into a full header, leaving the not needed     */
  1143.     pbmiBitmap->cbFix = 64;        /* fields with a value of 0             */
  1144.     usStorage = (USHORT)pbmiBitmap->ulCompression; /* Copy more parameters */
  1145.     usDepth = pbmiBitmap->cBitCount;               /* as depth,            */
  1146.     usSamples = pbmiBitmap->cPlanes;               /* no. of planes,       */
  1147.     usColors = (USHORT)(1 << usDepth);             /* and no. of colors    */
  1148.     break;                                         /* finished with BMP's  */
  1149.  
  1150.   case GIF:                        /* File is a GIF                        */
  1151.     if ((lReturn = gifrhdr (hImage, pbmiBitmap)) == 0) { /* Get header     */
  1152.       ulSizeX = pbmiBitmap->cx;      /* Copy some parameters into globals  */
  1153.       ulSizeY = pbmiBitmap->cy;
  1154.       usStorage = 0;                 /* Not needed with GIF's              */
  1155.       usColors = (USHORT)(1 << pbmiBitmap->cBitCount); /* Get no. of colors*/
  1156.       switch (pbmiBitmap->cBitCount) { /* OS/2 needs bitcount of 1, 4, or 8*/
  1157.       case 2:
  1158.       case 3:
  1159.       case 4:
  1160.         pbmiBitmap->cBitCount = 4;
  1161.         break;
  1162.       case 5:
  1163.       case 6:
  1164.       case 7:
  1165.       case 8:
  1166.         pbmiBitmap->cBitCount = 8;
  1167.         break;
  1168.       } /* endswitch */
  1169.       usDepth = pbmiBitmap->cBitCount;
  1170.       usSamples = pbmiBitmap->cPlanes;
  1171.       if (usDepth != 24) { /* Don't know if there are 24 bit GIF's??       */
  1172.         pbmiBitmap->cclrUsed = usColors; /* Palette manager can maybe make */
  1173.         pbmiBitmap->cclrImportant = usColors; /* use of this fields        */
  1174.       } 
  1175.     } else { /* If we couldn't read the GIF header, display an error msg.  */
  1176.       ShowMsg (IDS_GIFERR, -lReturn, MB_ERROR);
  1177.       return 1;
  1178.     }
  1179.     break; /* Finished with GIF's */
  1180.  
  1181.   case IM:  /* File is an IM                                               */
  1182.     if (imrhdr (imBild)) {          /* Get header                          */
  1183.       ImErrorMsg (imerrnum);        /* If error, display message           */
  1184.       return 0;
  1185.     }
  1186.     ulSizeX = imgetxsize(imBild);   /* Get some properties of the picture  */
  1187.     ulSizeY = imgetysize(imBild);
  1188.     usType  = imgettype (imBild);
  1189.     if (usType == IMFLT) {          /* IMFLT can't be displayed            */
  1190.       ShowMsg (IDS_ERRTITLE, IDS_FLTERR, MB_ERROR);
  1191.       return 0;
  1192.     }
  1193.     usStorage = imgetstor (imBild); /* Get some more properties            */
  1194.     usDepth = imgetdepth (imBild);
  1195.     usSamples = imgetsamples (imBild);
  1196.     if (usType == IMGRY)            /* IMGRY gives wrong no. of colors     */
  1197.       usColors = (USHORT)(1 << usDepth);
  1198.     else
  1199.       usColors = (USHORT)imgetcolors (imBild);
  1200.  
  1201.                                 /* Allocate row buffer                     */
  1202.     imbRowBuff = imrowalloc ((USHORT)ulSizeX, usSamples, usDepth);
  1203.     if (imbRowBuff == NULL) return 1;
  1204.  
  1205.     switch (usType) {  /* Further processing different for the IM types    */
  1206.     case IMRGB: /* IMRGB is a 24 bit, no colormapped, RGB picture          */
  1207.       /* Allocate room for IM header                                       */
  1208.       pbmiBitmap->cBitCount = 24;
  1209.       break;
  1210.  
  1211.     case IMGRY: /* IMGRY is a grayscale, with no explicit colormap         */
  1212.       if (usDepth < 3)                   /* Set bitdepth to 1,2,4 or 8     */
  1213.         pbmiBitmap->cBitCount = usDepth;
  1214.       else if (usDepth < 5)           
  1215.         pbmiBitmap->cBitCount = 4;
  1216.       else 
  1217.         pbmiBitmap->cBitCount = 8;
  1218.       pbmiBitmap->cclrUsed = usColors;
  1219.       pbmiBitmap->cclrImportant = usColors;
  1220.      /*********************************************************************/
  1221.      /* OS/2 doesn't know about grayscales with no explicit colormap,     */
  1222.      /* so we have to generate a gray colormap.                           */
  1223.      /*********************************************************************/
  1224.       ulTemp = (255 / ((1<<(ULONG)usDepth)-1)); /* Calculate increment     */
  1225.       for (ulIndex = 0; ulIndex < (1<<(ULONG)usDepth); ulIndex++) {
  1226.         pbmiBitmap->argbColor[ulIndex].bBlue  = (BYTE)(ulIndex * ulTemp);
  1227.         pbmiBitmap->argbColor[ulIndex].bGreen = (BYTE)(ulIndex * ulTemp);
  1228.         pbmiBitmap->argbColor[ulIndex].bRed   = (BYTE)(ulIndex * ulTemp);
  1229.       } /* End for */
  1230.       break;
  1231.  
  1232.     case IMMAP:
  1233.       pimMap = (IMBYTE *)immapalloc (usColors); /* Allocate colormap       */
  1234.       imsetcmap (imBild, (IMPIXEL *)pimMap);    /* Set pointer to colormap */
  1235.       if (imrcmap (imBild)) {                   /* Get colormap            */
  1236.         ImErrorMsg (imerrnum);
  1237.         return 0;
  1238.       }
  1239.  
  1240.       if (usColors > 257) {                     /* Too much colors...      */
  1241.         pbmiBitmap->cBitCount = 24;             /* So make an RGB picture  */
  1242.  
  1243.       } else {                                  /* No. colors ok           */
  1244.         if (usColors > 16)               /* 32 to 256 colors: 8 Bits       */
  1245.           pbmiBitmap->cBitCount = 8;     /*                                */
  1246.         else if (usColors > 4)           /*  8 to  16 colors: 4 Bits       */
  1247.           pbmiBitmap->cBitCount = 4;     /*                                */
  1248.         else if (usColors > 2)           /*         4 colors: 2 Bits       */
  1249.           pbmiBitmap->cBitCount = 2;
  1250.         else                     
  1251.           pbmiBitmap->cBitCount = 1;     /*         2 colors: 1 Bit        */
  1252.         pbmiBitmap->cclrUsed = usColors;
  1253.         pbmiBitmap->cclrImportant = usColors;
  1254.       } /* End if too much colors */
  1255.  
  1256.       /* Copy colormap into header:                                        */
  1257.       for (ulIndex = 0; ulIndex < usColors; ulIndex++) {
  1258.         pbmiBitmap->argbColor[ulIndex].bBlue  = *(pimMap + 4*ulIndex + 2);
  1259.         pbmiBitmap->argbColor[ulIndex].bGreen = *(pimMap + 4*ulIndex + 1);
  1260.         pbmiBitmap->argbColor[ulIndex].bRed   = *(pimMap + 4*ulIndex);
  1261.       } /* End for */
  1262.       free (pimMap);  /* Release IM colormap                               */
  1263.       break;
  1264.     } /* End switch */
  1265.  
  1266.     pbmiBitmap->cbFix     = 64; /* Again common for all IM types           */
  1267.     pbmiBitmap->cx        = ulSizeX;
  1268.     pbmiBitmap->cy        = ulSizeY;
  1269.     pbmiBitmap->cPlanes   = 1;
  1270.     break;
  1271.  
  1272.   case IMERROR:   /* Type was an IM, but there was some sort of error      */
  1273.     ImErrorMsg (imerrnum);         /* Display this error                   */
  1274.     return 0;
  1275.  
  1276.   case UNKNOWN:                    /* Picture type is not supported        */
  1277.     ShowMsg (IDS_ERRTITLE, IDS_TYPEERR, MB_ERROR);
  1278.     return 0;
  1279.  
  1280.   default:                         /* Shouldn't occur                      */
  1281.     return 0;
  1282.   } /* endswitch */
  1283.  
  1284.   /*************************************************************************/
  1285.   /*                                                                       */
  1286.   /* Until now we got the bitmap header. Next we will load the image       */
  1287.   /* data into a buffer.                                                   */
  1288.   /*                                                                       */
  1289.   /*************************************************************************/
  1290.   strcat (szFileSource, " (imShow 2.02)");
  1291.   WinSetWindowText (hwndFrame, szFileSource); /* Set window title          */
  1292.  
  1293.   /* We have to know this global variable:                                 */
  1294.   ulBytesPerLine = ((pbmiBitmap->cBitCount * pbmiBitmap->cx + 31) / 32
  1295.                       * pbmiBitmap->cPlanes * 4);
  1296.  
  1297.   pbBitmapData = malloc(ulBytesPerLine * pbmiBitmap->cy); /* Alloc Buffer  */
  1298.   if (pbBitmapData == NULL) exit(1);          /* No good error handling... */
  1299.  
  1300.  /************************************************************************/
  1301.  /* At this place was a very hard to find race condition: I cleared      */
  1302.  /* the semaphore (which tells the loading thread to start) before I     */
  1303.  /* created the dialog. On VERY small pictures, the thread was finished  */
  1304.  /* before the dialog box was properly initialized. The message from the */
  1305.  /* thread to the dialog (telling it is finished) couldn't be delivered, */
  1306.  /* and there we had the Trap D...                                       */
  1307.  /* Now it works.                                                        */
  1308.  /************************************************************************/
  1309.   hwndDlg = WinLoadDlg(HWND_DESKTOP,     /* Load "cancel" dialog         */
  1310.                        hwnd,
  1311.                        (PFNWP)CancelDlgProc,
  1312.                        0,
  1313.                        IDD_CANCEL,
  1314.                        NULL);
  1315.  
  1316.   DosResetEventSem (semPictureReady, &ulSemHelper); /* Picture not ready   */
  1317.   DosPostEventSem (semInputReady);       /* Loading thread can start       */
  1318.  
  1319.   WinProcessDlg (hwndDlg);               /* Process messages to dialog     */
  1320.   WinDestroyWindow (hwndDlg);            /* After finishing, clear it      */
  1321.  
  1322.   if (fPicReadOK == TRUE) {        /* The picture was read in successfully */
  1323.     /* Now we reset and allocate some ressources:                          */
  1324.     SetScrollBars(lScaleFactor);              /* Initialize scrollbars     */
  1325.   
  1326.     if (*hbm != (HBITMAP) NULL) {        /* Is there a bitmap from before? */
  1327.       if (hpal != NULLHANDLE) {            /* Did we have a palette?       */
  1328.         GpiSelectPalette (hps, NULLHANDLE);  /* Yes: Release it            */
  1329.         GpiDeletePalette (hpal);
  1330.         hpal = NULLHANDLE;
  1331.       }
  1332.       GpiSetBitmap (hps, (HBITMAP)NULL);      /* Release bitmap here..     */
  1333.       if (hpsMem != NULLHANDLE) {
  1334.         GpiSetBitmap (hpsMem, (HBITMAP)NULL);   /* or maybe here,          */
  1335.         GpiDeleteBitmap (*hbm);                 /* and delete it           */
  1336.         GpiAssociate (hpsMem, (HDC)NULL);       /* and old memory          */
  1337.         GpiDestroyPS (hpsMem);                  /*  presentation space     */
  1338.         hpsMem = NULLHANDLE;
  1339.         DevCloseDC(hdcMem);                     /* Close memory dev. cont. */
  1340.       } else
  1341.         GpiDeleteBitmap (*hbm);                 /* Else delete only bitmap */
  1342.     }
  1343.   
  1344.     GpiResetPS (hps, GRES_ALL);      /* Make shure the PS is "fresh" again */
  1345.   
  1346.     if (pbBitmapData == NULL)                          /* something wrong? */
  1347.       return (1);
  1348.   
  1349.     if (bRealizeSupported &&         /* Can we realize the palette?        */
  1350.         ((USHORT)ulDisplayColors >= (1 << pbmiBitmap->cBitCount))) {
  1351.       MakePalette (pbmiBitmap, &plColTable); /* Make new palette           */
  1352.       *hbm = GpiCreateBitmap(hps,            /* Make new bitmap            */
  1353.                              (PBITMAPINFOHEADER2)pbmiBitmap,
  1354.                              CBM_INIT,            /* Initialize it with    */
  1355.                              (PBYTE)pbBitmapData, /* data in buffer        */
  1356.                              pbmiBitmap
  1357.                             );
  1358.       GpiSetBitmap(hps, *hbm);                /* Select bitmap in HPS      */
  1359.       DosPostEventSem (semPictureReady);   /* Picture is now ready         */
  1360.       WinInvalidateRect (hwnd, NULL, FALSE);  /* Force redraw              */
  1361.   
  1362.     } else {                             /* We can't realize the palette   */
  1363.       /* First create a memory device context:                             */
  1364.       hdcMem = DevOpenDC(hab,                     /* Anchor block handler  */
  1365.                          OD_MEMORY,               /* Memory device context */
  1366.                          (PSZ)"*",                /* no device information */
  1367.                          0,                       /* no datablocks         */
  1368.                          NULL,                    /* no datablocks         */
  1369.                          NULLHANDLE             /* compatible to screen-DC */
  1370.                         );
  1371.       if (hdcMem == (HDC)NULL)                    /* Not a very nice error */
  1372.         exit(1);                                  /* handling...           */
  1373.  
  1374.       hpsMem = GpiCreatePS(hab,               /* We need a memory PS       */
  1375.                     hdcMem,                   /*  for hdcMem               */
  1376.                     (PSIZEL)&size,
  1377.                     (LONG)PU_PELS | GPIT_NORMAL | GPIA_ASSOC | GPIF_DEFAULT
  1378.                           );
  1379.       if (hpsMem == (HPS)NULL) exit(1); /* Some day I will improve this..  */
  1380.  
  1381.       *hbm = GpiCreateBitmap(hpsMem,          /* Create bitmap             */
  1382.                              (PBITMAPINFOHEADER2)pbmiBitmap,
  1383.                              0L,              /* Don't init it             */
  1384.                              (PBYTE)NULL,
  1385.                              0
  1386.                             );
  1387.       if (*hbm == (HBITMAP)NULL) exit(1);
  1388.  
  1389.       GpiSetBitmap(hpsMem, *hbm);             /* Select bitmap into PS     */
  1390.  
  1391.        /* and now set the bitmap bits into the bitmap                     */
  1392.        /* This can take a while, so let's set the clock pointer:          */
  1393.       WinSetPointer (HWND_DESKTOP, hptrWait);
  1394.       GpiSetBitmapBits (hpsMem, 0, (LONG)ulSizeY, pbBitmapData, pbmiBitmap);
  1395.       WinSetPointer (HWND_DESKTOP, hptrArrow); /* Reset the pointer..     */
  1396.  
  1397.        /* If we realized before, this will undo it:                       */
  1398.       WinRealizePalette (hwndClient, 0, &ulTemp);
  1399.       fRealized = FALSE;
  1400.  
  1401.       DosPostEventSem (semPictureReady);  /* Picture is ready to display   */
  1402.       WinInvalidateRect (hwnd, NULL, FALSE); /* Force redraw               */
  1403.     } /* End if "can we realize" */
  1404.   free (pbBitmapData);                       /* Release Buffer             */
  1405.  
  1406.   } else /* Picture was not read in successfully: */
  1407.       WinInvalidateRect (hwnd, NULL, FALSE); /* Clears client area         */
  1408.  
  1409.   return 1;
  1410. }
  1411. /***************************  End of OpenFile()  ***************************/
  1412.  
  1413.  
  1414. /**********************  Begin of the thread ReadFile  *********************/
  1415. /*                                                                         */
  1416. /* The thread ReadFile() reads in the picture data asynchronously.         */
  1417. /* It is implemented as an endless loop and is contolled via semaphores.   */
  1418. /*                                                                         */
  1419. /***************************************************************************/
  1420. VOID ReadFile (VOID* nothing)    /* We HAVE to to this for _beginthread..  */
  1421. {
  1422.  
  1423. PBYTE    pbTemp;                         /* 2nd pointer to bitmapdata      */
  1424. register ULONG   x,y;                    /* Loop variables                 */
  1425. ULONG    ulProgress;                     /* For the progress indicator     */
  1426. IMPIXEL  impPixel;                       /* One IM pixel                   */
  1427. ULONG    ulChunk;                        /* Size of a data block           */
  1428.          
  1429.   while (TRUE) {                         /* Start of endless loop          */
  1430.     DosWaitEventSem (semInputReady, SEM_INDEFINITE_WAIT);/* Wait here...   */
  1431.     DosResetEventSem (semInputReady, &ulSemHelper); /* Reset semaphore     */
  1432.     fPicReadOK = FALSE;                  /* Picture (not yet) ok           */
  1433.  
  1434.     switch (usType) {                     /* Read depending on type        */
  1435.       case OS2_101:                       /* The bitmap DATA is equal on   */
  1436.       case WIN_3:                         /* all types, only the header    */
  1437.       case OS2_200:                       /* differs                       */
  1438.         bmrrows (hImage, pbBitmapData, 0, ulSizeY); /* Get all at once     */
  1439.         WinPostMsg (hwndDlg, WM_PROGRESS, MPFROMSHORT(100), 0L); /* dummy  */
  1440.         fPicReadOK = TRUE;                /* read in ok                    */
  1441.       break;                              /* that's it...                  */
  1442.  
  1443.       case IMRGB:                         /* IM type IMRGB (24 bit)        */
  1444.         /*******************************************************************/
  1445.         /* Unfortunately, the picture data of IM is different from OS/2... */
  1446.         /*******************************************************************/
  1447.         for (y=ulSizeY; y>0; y--) {  /* OS/2 bitmaps stand on head...      */
  1448.           /* Here we test the semaphore semHalt. It will be set when the   */
  1449.           /* user chooses "ESC=Cancel" on the dialog. We don't want to     */
  1450.           /* wait for the semaphore, we just want to see if it is set:     */
  1451.           if (DosWaitEventSem (semHalt, 0L) == ERROR_TIMEOUT)
  1452.             goto Halt; /* Not very elegant, but by far the easiest way...  */
  1453.           /* Read one row of image data:                                   */
  1454.           if ((!imrrow (imBild, imbRowBuff) && imerrnum)) {
  1455.             ImErrorMsg (imerrnum);
  1456.             goto Halt;
  1457.           }
  1458.           pbTemp = pbBitmapData + (y-1)*ulBytesPerLine; /* Get this out of */
  1459.                                                     /* the inner loop      */
  1460.           for (x=0; x<ulSizeX; x++) {      /* Now we have to calculate:    */
  1461.             /***************************************************************/
  1462.             /* IM stores the image data sorted by color, i.e. RRRGGGBBB.   */
  1463.             /* OS/2 on the other hand stores it pixelwise, i.e. RGBRGBRGB. */
  1464.             /* So we have to shuffle it:                                   */
  1465.             /***************************************************************/
  1466.             *(pbTemp+x+x+x+2) = *(imbRowBuff+x                );
  1467.             *(pbTemp+x+x+x+1) = *(imbRowBuff+x+ulSizeX        );
  1468.             *(pbTemp+x+x+x  ) = *(imbRowBuff+x+ulSizeX+ulSizeX);
  1469.           } /* Ende for x */
  1470.           ulProgress = 100 - (100 * y / ulSizeY);  /* Calculate progress   */
  1471.           WinPostMsg (hwndDlg, WM_PROGRESS, MPFROMSHORT(ulProgress), 0L);
  1472.         } /* Ende for y */
  1473.         fPicReadOK = TRUE;
  1474.         break;
  1475.  
  1476.       case IMGRY:               /* The image data is the same with IMMAP   */
  1477.       case IMMAP:               /* and IMGRY.                              */
  1478.         if (usColors < 257) {   /* IMMAP can have more than 256 colors in  */
  1479.                                 /* the colormap, OS/2 not.                 */
  1480.           for (y=ulSizeY; y>0; y--) {
  1481.             if (DosWaitEventSem (semHalt, 0L) == ERROR_TIMEOUT) /* Test    */
  1482.               goto Halt;
  1483.             imrrow (imBild, pbBitmapData+(y-1)*ulBytesPerLine); /* Get row */
  1484.             ulProgress = 100 - (100 * y / ulSizeY);        /* Set progress */
  1485.             WinPostMsg (hwndDlg, WM_PROGRESS, MPFROMSHORT(ulProgress), 0L);
  1486.           } /* Ende for y */
  1487.           fPicReadOK = TRUE;                           /* Finished..       */
  1488.         } else {                /* With more than 256 colors we have to    */
  1489.                                 /* use a 24 bit picture in OS/2.           */
  1490.           for (y=ulSizeY; y>0; y--) {  /* Work row by row                  */
  1491.             if (DosWaitEventSem (semHalt, 0L) == ERROR_TIMEOUT) /* Test    */
  1492.               goto Halt;
  1493.             if ((!imrrow (imBild, imbRowBuff)) && imerrnum) { /* Get row   */
  1494.               ImErrorMsg (imerrnum);
  1495.               goto Halt;
  1496.             }
  1497.             /***************************************************************/
  1498.             /* Now we use IM's 'ideal pixel' function to calculate the 24  */
  1499.             /* bit value of each pixel and store it into the bitmap buffer */
  1500.             /***************************************************************/
  1501.             for (x=0; x<ulSizeX; x++) {    /* Work pixel for pixel         */
  1502.               impPixel = imrpix (imBild, imbRowBuff, (USHORT)x); 
  1503.               pbTemp = pbBitmapData + (y-1)*ulBytesPerLine + x+x+x;
  1504.               *(pbTemp+2) = (BYTE)((impPixel & 0x0000FF));
  1505.               *(pbTemp+1) = (BYTE)((impPixel & 0x00FF00) >>  8);
  1506.               *(pbTemp  ) = (BYTE)((impPixel & 0xFF0000) >> 16);
  1507.             }
  1508.             ulProgress = (USHORT) ((100L * (LONG)y) / (LONG)ulSizeY);
  1509.             WinPostMsg (hwndDlg, WM_PROGRESS, MPFROMSHORT(ulProgress), 0L);
  1510.           } /* Ende for y */
  1511.           fPicReadOK = TRUE;    /* That's it                               */
  1512.         } /* Ende if */
  1513.         break;
  1514.      case GIF:                      /* GIF File                            */
  1515.        ulChunk = ulSizeY / 20;      /* Read in in 20 "bites"               */
  1516.        for (y=1; y<21; y++) {       /* Check                               */
  1517.          if (DosWaitEventSem (semHalt, 0L) == ERROR_TIMEOUT)
  1518.            goto Halt;
  1519.          pbTemp = pbBitmapData + (ulSizeY - y * ulChunk) * ulBytesPerLine;
  1520.          gifrrows (hImage, pbTemp, ulSizeX, ulChunk); /* Get the rows      */
  1521.          ulProgress = (USHORT) y*5;                   /* Set progress      */
  1522.          WinPostMsg (hwndDlg, WM_PROGRESS, MPFROMSHORT(ulProgress), 0L);
  1523.        } /* endfor */
  1524.        ulChunk = ulSizeY % 20;        /* Do we have some last rows?        */
  1525.        if (ulChunk > 0)               /* If so, read them in               */
  1526.          gifrrows (hImage, pbBitmapData, ulSizeX, ulChunk);
  1527.        fPicReadOK = TRUE;             /* That's it                         */
  1528.        break;
  1529.  
  1530.     } /* End switch */
  1531.  
  1532.     Halt:                             /* To this place we jump after the   */
  1533.                                       /* read in was cancelled.            */
  1534.  
  1535.     DosPostEventSem (semHalt);        /* Erase semaphore                   */
  1536.  
  1537.     if (fPicReadOK == FALSE)          /* Picture was not read in           */
  1538.       free (pbBitmapData);            /* free the buffer                   */
  1539.     if (imbRowBuff != NULL)           /* If we have one, free this as      */
  1540.       free (imbRowBuff);              /*  well                             */
  1541.  
  1542.     switch (usType) {
  1543.       case OS2_101:
  1544.       case WIN_3:
  1545.       case OS2_200:
  1546.         bmclose (hImage);             /* Close the image files             */
  1547.         break;
  1548.       case GIF:
  1549.         gifclose (hImage);
  1550.         break;
  1551.       default: 
  1552.         imclose (imBild);
  1553.     }
  1554.  
  1555.     WinPostMsg (hwndDlg, WM_FINISHED, 0L, 0L);  /* Inform the dialog box   */
  1556.                                                 /* that we are finished    */
  1557.   } /* End of endless loop */
  1558. }
  1559. /*************************  End of thread ReadFile  ************************/
  1560.  
  1561.  
  1562.  
  1563.  
  1564. /**************************  Start of ShowMsg  *****************************/
  1565. /*                                                                         */
  1566. /* The function ShowMsg display a message.                                 */
  1567. /*                                                                         */
  1568. /***************************************************************************/
  1569.  
  1570. VOID ShowMsg (LONG lTitle, LONG lMessage, ULONG ulIcon)
  1571. {
  1572.   char cTitle[32];
  1573.   char cMessage[255];
  1574.  
  1575.    /* First the message title and the message content will be loaded       */
  1576.    /* from the ressource part:                                             */
  1577.   WinLoadString (hab, 0, lTitle, sizeof cTitle, cTitle);
  1578.   WinLoadString (hab, 0, lMessage, sizeof cMessage, cMessage);
  1579.  
  1580.   WinMessageBox (HWND_DESKTOP,   /* Then the message will be displayed     */
  1581.                  hwndFrame,
  1582.                  cMessage,
  1583.                  cTitle,
  1584.                  IDD_ERRORS,
  1585.                  MB_OK | ulIcon);
  1586. }
  1587. /****************************  End of ShowMsg  *****************************/
  1588.  
  1589.  
  1590.  
  1591. /**************************  Start of ImErrorMsg  **************************/
  1592. /*                                                                         */
  1593. /* ImErrorMsg shows an error message of the IM library.                    */
  1594. /*                                                                         */
  1595. /***************************************************************************/
  1596.  
  1597. VOID ImErrorMsg (int iMessageNum)
  1598. {
  1599.   char cTitle[32];
  1600.  
  1601.    /* First we get the title of the message box:                           */
  1602.   WinLoadString (hab, 0, IDS_IMTITLE, sizeof cTitle, cTitle);
  1603.  
  1604.   WinMessageBox (HWND_DESKTOP,   /* Then we show the message               */
  1605.                  hwndFrame,
  1606.                  imerrors[iMessageNum],
  1607.                  cTitle,
  1608.                  IDD_ERRORS,
  1609.                  MB_OK | MB_ERROR);
  1610. }
  1611.  
  1612. /***************************  End of ImErrorMsg  ***************************/
  1613.  
  1614.  
  1615.  
  1616. /************************  Start of GetFileType  ***************************/
  1617. /*                                                                         */
  1618. /* GetFileType gives the type of the stated file.                          */
  1619. /*                                                                         */
  1620. /***************************************************************************/
  1621. USHORT GetFileType (CHAR *szFileName, HFILE *hImage, IMAGE **imBild)
  1622. {
  1623.   *hImage = bmopen (szFileName, "rb");           /* Try to open bitmap     */
  1624.   if (*hImage != 0)                              /* ok?                    */
  1625.     return (BITMAP);
  1626.  
  1627.   *hImage = gifopen (szFileName, "rb");          /* Try to open GIF        */
  1628.   if (*hImage != 0)                              /* ok?                    */
  1629.     return (GIF);
  1630.  
  1631.   *imBild = imopen (szFileName, "r");            /* Try to open IM         */
  1632.     if (*imBild == NULL)                         /* ok?                    */
  1633.       if (imerrnum == 5)                         /* error 5 is "not im"    */
  1634.         return (UNKNOWN);          /* So give back "unknown"               */
  1635.       else                         /* File is IM, but there's another      */
  1636.         return (IMERROR);          /*   problem                            */
  1637.     else return (IM);
  1638. }
  1639. /***************************  End of GetFileType  **************************/
  1640.